#include "DIVA_Manager.h"
#include "ubrvm_autounfold.h"
#include "vmLibrary.h"
#define COLOR_MODULATE_PARAM_INDEX 1
// @@@@
/// constructor
//Name           : hyt
//Update Date    : 08/10/26
//Update History :
//				(1) VL_createEntity 必須給 meshname,material可給可不給,若想自行命名vm的開頭,則可以
//                   再加第三個參數 string specialhead
//              (2) VL_regBoudingBox 則需要 vm的entity 
//              (3) 由programmer自行決定node內容
//              (4) 若要在vm任何一個位置顯示文字,首先呼叫VL_createVMText(你想顯示的文字,文字node的開頭name)
//                  再來是呼叫VL_createTextNode(vm文字位置)
//              (5) 設定vm node顏色則呼叫VL_setEntityColor(vm entity , Vector4(colorvalue))來設定
ubrvm_autounfold::ubrvm_autounfold(xParameterPack xpp):ReferenceVM(xpp){
	int default_port_number = vmLibrary::instance().get_vm_default_input_parameters().size();

	// reference vm is designed based on a proxy pattern
	// first, a reference vm has its own body
	// second, it must points to a vm (called pointed vm)
	// however, this pointed vm can be any vm and changed from time to time
	// so, a fixed vm passed to the constructor's parameters would not work.
	// so, a pragmatic way is to allowed user connect wop to a variable
	// in xNodeType_VM::createMappedObject(), we scan for hidden vm inport immediately
	// behind the wop. If there is a hidden vm inport, we use the wop to create a dummy vm
	// and feed this dummy as the parameter of the vm.  This dummy vm is designed based
	// on proxy pattern. The dummy vm is responsible for evaluating the wop value, search the 
	// represented VM and redirect the events and action to the vm.

	assert(xpp.no == default_port_number+2);
	_pointedVM = xpp.paras[default_port_number+1].val_vm ;  // @@@@ this _pointedVM is actually a dummyVM
	_proxyVM = (dummyVM *) _pointedVM ; // @@@@ cast it to dummyVM to use the method  isPointedNULL()
	//_shapeVM = xpp.paras[default_port_number+2].val_vm ; // this is the VM which is used to 

	_myLine = false;
	_firstclicked = true;
	_line_node = NULL;
	

	VL_addVMAnimation();
	init_default_parameters(); // this line must be added at the end of each VM constructor
	enableVMAnimation();
}

/// destructor
ubrvm_autounfold::~ubrvm_autounfold(){
}
void ubrvm_autounfold::load_3Dresources(){
	//std::string meshName = "cube.mesh";
	///// create entity and attach to the newly allocated scene node
	//_ent = VL_createEntity(meshName,"TextureModColor");
	//_SceneNode->attachObject(_ent);

	//this->scaleBodyToAbsSize(0, 0, 0); 

}
void ubrvm_autounfold::reg_event_entity() {

	// register the relation of the entity and vm in diva manager
	// When this entity is clicked, mouse/keyboard VM will be passed to this VM
	// By default it can be only one entity representing this VM
	// VL_regBoundingBox(_ent);
}
void ubrvm_autounfold::set_default_values() {

	_vm_rx_val = 0 ;
	_vm_ry_val = 0 ;
	_vm_rz_val = 0 ;

	Ogre::Vector3 sz = this->getActualSize();
	_vm_init_sizex = sz.x ;
	_vm_init_sizey = sz.y ;
	_vm_init_sizez = sz.z ;

	_vm_sizex_val = sz.x ;
	_vm_sizey_val = sz.y ;
	_vm_sizez_val = sz.z ;

	_vm_sizexscale_val = 1.0 ;
	_vm_sizeyscale_val = 1.0 ;
	_vm_sizezscale_val = 1.0 ;

	_vm_r_val = 0.5;  // white color but with transparency 0.1
	_vm_g_val = 0.5;
	_vm_b_val = 0.5;
	_vm_transparency_val = 0.2 ;

	_vm_yaw_val = 0 ;
	_vm_pitch_val = 0 ;
	_vm_roll_val = 0 ;

}
void ubrvm_autounfold::init_private_attrs_started() {

}
void ubrvm_autounfold::init_color_and_transparency() {
	// we do not have entity in this VM
	// so we need to do nothing for color and transparency

}
void ubrvm_autounfold::update_color_and_transparency() {
	init_color_and_transparency();
}
void ubrvm_autounfold::VMValueUpdated() {
	_proxyVM->clearPointedVM();
	_firstclicked = true;

	// the value of pointer is updated so that now autounfold points to a new vm
	// the old vm is stored by _current we want to deattach it from this scenenode
	if(_currentSceneNode != NULL){
		_SceneNode->removeChild(_currentSceneNode);
		_currentparent->addChild(_currentSceneNode);
		_currentvm->setParentSceneNode(_currentparent);
	} 
	VMPicked(0,0,0);
	
}
void ubrvm_autounfold::VMAnimation(const Ogre::FrameEvent & evt){
	if (_visible == false)  return ;
	if (_firstclicked) {
		VMPicked(0,0,0); // force the VMPicked to be called immediately the VM is created.
	}
	//_vm_rx_val = *(_proxyVM->getBodyVM()->get_vm_rx());
	//_vm_ry_val = *(_proxyVM->getBodyVM()->get_vm_ry());
	//_vm_rz_val = *(_proxyVM->getBodyVM()->get_vm_rz());

}
void ubrvm_autounfold::VMSetVisible(bool vis) {
	if (_visible != vis) {
		  _visible = vis ;
        _SceneNode->setVisible(vis);
		//_shapeVM->VMSetVisible(vis);
	}
}
void ubrvm_autounfold::VMPicked(Ogre::Real x,Ogre::Real y,Ogre::Real z){
	//enableVMAnimation();
	if (! _proxyVM->hasNULLvalue()) { //@@@@ 
		if (_firstclicked) {
			Ogre::Vector3 start = getWorldPosition() ;
			Ogre::Vector3 end = _proxyVM->getWorldPosition(); // make the value to be unfolded.

			// deattch proxyVM's scenenode and attach to this one.
			// remember _proxyVM is a proxy pattern. It actually represent the pointed VM
			// all the method of _proxyVM is passed to the pointed VM
			Ogre::SceneNode *parent = _proxyVM->getParentSceneNode() ;
			Ogre::SceneNode *s = _proxyVM->getSceneNode();
			parent->removeChild(s);
			_SceneNode->addChild(s);
			_currentSceneNode = s ;
			_currentparent = parent ;
			_currentvm = _proxyVM->getBodyVM();

			_proxyVM->setParentSceneNode(_SceneNode);
			s->setInheritScale(false);

			// create entity and attach to the newly allocated scene node
			// only if haven't created before
			if( this->_ent == NULL ) {
				std::string meshName = "cube.mesh";
				_ent = VL_createEntity(meshName,"TextureModColor");
				//this->setPosition(_proxyVM->getPosition());
				_ent->setVisible(false);
				float* sizex = _proxyVM->getBodyVM()->get_vm_sizex();
				float* sizey = _proxyVM->getBodyVM()->get_vm_sizey();
				float* sizez = _proxyVM->getBodyVM()->get_vm_sizez();
				this->scaleBodyToAbsSize(*sizex, *sizey, *sizez);
			}

			// 如果 autounford 沒有被指定位置，則使用 proxyVM 的位置；如果有就用指定的位置來設定 proxyVM
			if ( this->getPosition()== Ogre::Vector3(0,0,0) ){
				this->setPosition(_proxyVM->getPosition());
			}

			// TODO: 2darray會assign位置給autounfold，autounfold要把位置assign給children
			this->scaleBodyToAbsSize(_proxyVM->getActualSize());

			//_proxyVM->disableVMDraggeed();
			_firstclicked = false ;

		} else
			_proxyVM->VMPicked(x,y,z);

	} else {  //@@@@
		// this is the case where a pointer has value NULL or 0
		// give the VM a black color 
		//this->scaleBodyToAbsSize(0, 0, 0); 
		_currentSceneNode = NULL;
		//this->setColorandTransparency(Ogre::Vector4(0.0f, 0.0f, 0.0f, 0.0f));
		// VL_setEntityColor(_ent,);		
	}
}

void ubrvm_autounfold::VMDragged(Ogre::Real screenx,Ogre::Real screeny,
								 Ogre::Real x,Ogre::Real y,Ogre::Real z){
	if (isDraggedOn()) {           // only when _dragged is true then we can set the position
		//this->setPosition(Ogre::Vector3(x,y,z));
		_proxyVM->setPosition(Ogre::Vector3(x,y,z)); 
	}
}

/** we must override this method because this vm has no entity 
Its entity is at _shapeVM 
*/
void ubrvm_autounfold::setBodyScale(Ogre::Vector3 scale) {
	_SceneNode ->setScale(scale);
}
//bool ubrvm_autounfold::isBodyScaleWrtSceneNode() { return true ; }

Ogre::Vector3 ubrvm_autounfold::getOriginalBodySize() {
	//Ogre::AxisAlignedBox temp = _ent ->getBoundingBox();	
	//Ogre::Vector3 size = temp.getSize(); 
	//return size ;
	return Ogre::Vector3(0,0,0);
}

Ogre::Vector3 ubrvm_autounfold::getActualSize() {
	return getOriginalBodySize() * _SceneNode->getScale();
}
Ogre::Vector3 ubrvm_autounfold::getBodyScale() {
	return _SceneNode->getScale();
}

